package com.xuelang.pipeline.app.pipeline.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.xuelang.hiforce.base.cache.client.service.DistributeCacheManager;
import com.xuelang.pipeline.app.msg.MsgUserMessagesService;
import com.xuelang.pipeline.app.pipeline.PipelineService;
import com.xuelang.pipeline.app.pipeline.SonarqubeService;
import com.xuelang.pipeline.app.resource.util.HttpUtil;
import com.xuelang.pipeline.app.resource.util.TektonUtil;
import com.xuelang.pipeline.app.resource.v1beta.pipeline.V1Beta1PipelineRun;
import com.xuelang.pipeline.client.common.constant.Constant;
import com.xuelang.pipeline.client.common.result.PageRecord;
import com.xuelang.pipeline.client.common.util.RedisHelper;
import com.xuelang.pipeline.client.msg.MsgConstant;
import com.xuelang.pipeline.client.msg.UserMessageSaveDTO;
import com.xuelang.pipeline.client.pipeline.dto.DeploymentUnitQuery;
import com.xuelang.pipeline.client.pipeline.dto.MeasDTO;
import com.xuelang.pipeline.client.pipeline.enums.*;
import com.xuelang.pipeline.client.resource.dto.ToolChainQuery;
import com.xuelang.pipeline.client.resource.enums.ToolChainTypeEnum;
import com.xuelang.pipeline.domain.pipeline.DeploymentUnit;
import com.xuelang.pipeline.domain.pipeline.Pipeline;
import com.xuelang.pipeline.domain.pipeline.PipelineInstance;
import com.xuelang.pipeline.domain.pipeline.TriggerSetting;
import com.xuelang.pipeline.domain.pipeline.service.DeploymentUnitDomainService;
import com.xuelang.pipeline.domain.pipeline.service.PipelineDomainService;
import com.xuelang.pipeline.domain.pipeline.service.PipelineInstanceDomainService;
import com.xuelang.pipeline.domain.pipeline.service.TriggerSettingDomainService;
import com.xuelang.pipeline.domain.resource.Cluster;
import com.xuelang.pipeline.domain.resource.Environment;
import com.xuelang.pipeline.domain.resource.Space;
import com.xuelang.pipeline.domain.resource.ToolChain;
import com.xuelang.pipeline.domain.resource.service.ClusterDomainService;
import com.xuelang.pipeline.domain.resource.service.EnvironmentDomainService;
import com.xuelang.pipeline.domain.resource.service.SpaceDomainService;
import com.xuelang.pipeline.domain.resource.service.ToolChainDomainService;
import com.xuelang.pipeline.domain.task.TaskInstance;
import com.xuelang.pipeline.domain.task.service.TaskInstanceDomainService;
import com.xuelang.pipeline.worker.client.common.result.ApiResult;
import com.xuelang.pipeline.worker.client.crd.IPipelineService;
import com.xuelang.pipeline.worker.client.crd.dto.PipelineRunDTO;
import com.xuelang.pipeline.worker.client.pod.IPodService;
import com.xuelang.pipeline.worker.client.pod.dto.QueryDTO;
import io.kubernetes.client.openapi.models.V1ContainerStatus;
import io.kubernetes.client.openapi.models.V1Pod;
import io.kubernetes.client.openapi.models.V1PodList;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.OffsetDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

/**
 * @author liuyuan.ly
 * @since 2024/7/8 10:57
 */
@Service
@Slf4j
@ConditionalOnProperty(prefix = "scheduling", name = "enabled", havingValue = "true")
public class PipelineWorkflowServiceImpl implements InitializingBean {

    @Autowired
    private DistributeCacheManager redisHelper;
    @Autowired
    private PipelineInstanceDomainService pipelineInstanceDomainService;
    @Autowired
    private TaskInstanceDomainService taskInstanceDomainService;
    @Autowired
    private IPipelineService tektonService;
    @Autowired
    private PipelineDomainService pipelineDomainService;
    @Autowired
    private EnvironmentDomainService environmentDomainService;
    @Autowired
    private SpaceDomainService spaceDomainService;
    @Autowired
    private ClusterDomainService clusterDomainService;
    @Autowired
    private IPodService podService;
    @Autowired
    private SonarqubeService sonarqubeService;
    private ScheduledExecutorService scheduledExecutorService;
    @Autowired
    private ToolChainDomainService toolChainDomainService;
    @Autowired
    private DeploymentUnitDomainService deploymentUnitDomainService;
    @Autowired
    private MsgUserMessagesService msgUserMessagesService;
    @Autowired
    private PipelineService pipelineService;
    @Autowired
    private TriggerSettingDomainService triggerSettingDomainService;
    @Autowired
    private TrackTaskServiceImpl trackTaskService;
    @Value("${pipeline.worker.url:}")
    private String workerAddress;

    @Scheduled(cron = "${devops.track.workflow:*/6 * * * * ?}")
    public void getRedisMq() {
//        log.info("polling for redis messages ..........");
        if (redisHelper.queueSize(Constant.WAIT_RUNNING_PIPELINE_QUEUE_KEY) > 0) {
            String pipelineInstanceCode = (String) redisHelper.dequeue(Constant.WAIT_RUNNING_PIPELINE_QUEUE_KEY);
            log.info("getRedisMq pipelineInstanceCode:{}", pipelineInstanceCode);
            TrackPipelineWorkflow(pipelineInstanceCode);
        }
    }

    private void TrackPipelineWorkflow(String pipelineInstanceCode) {
        PipelineInstance pipelineInstance = pipelineInstanceDomainService.queryByCode(pipelineInstanceCode);
        Pipeline pipeline = pipelineDomainService.query(pipelineInstance.getPipelineCode());
        String kubeConfig = getClusterKubeConfig(pipeline);

        TrackPipelineTask task = new TrackPipelineTask();
        task.setPipelineInstance(pipelineInstance);
        task.setKubeConfig(kubeConfig);
        task.setPipeline(pipeline);
        ScheduledFuture<?> future = scheduledExecutorService.scheduleAtFixedRate(task, 2, 3, TimeUnit.SECONDS);
        task.setFuture(future);
    }



    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    class TrackPipelineTask implements Runnable {
        private PipelineInstance pipelineInstance;
        private volatile ScheduledFuture<?> future;
        private String kubeConfig;
        private Pipeline pipeline;

        @Override
        public void run() {
            log.info("Task started at " + new Date() + " in thread " + Thread.currentThread().getName());
            try {
                trackPipelineInstance(pipelineInstance, kubeConfig, future, pipeline);
            } catch (Exception e) {
//                Thread.currentThread().interrupt();
                log.error("Polling task was error ", e);
            }

            log.info("Task completed at " + new Date() + " in thread " + Thread.currentThread().getName());
        }
    }


    private void trackPipelineInstance(PipelineInstance pipelineInstance, String kubeConfig, ScheduledFuture<?> future, Pipeline pipeline) {
        String pipelineInstanceCode = pipelineInstance.getInstanceCode();
        PipelineRunDTO pipelineRunDTO = new PipelineRunDTO();
        pipelineRunDTO.setPipelineRunName(pipelineInstanceCode);
        pipelineRunDTO.setKubeConfig(kubeConfig);
        pipelineRunDTO.setNamespaceName(Constant.BUILD_NAMESPACE);
        List<V1Beta1PipelineRun> listData = new ArrayList<>();
        try {
            String respDTO = HttpUtil.doPost(Constant.HTTP_URL_PREFIX + workerAddress + Constant.WORKER_GET_PIPELINE_RUN_URL, JSON.toJSONString(pipelineRunDTO));
            ApiResult basicRespDTO = JSONObject.parseObject(respDTO, ApiResult.class);
            String podData = (String) basicRespDTO.getData();
            listData = JSON.parseArray(podData, V1Beta1PipelineRun.class);
        } catch (IOException e) {
            log.error("获取远程worker的pipelinerun信息失败", e);
//            throw new RuntimeException(e);
        }


//        String string = stringApiResult.getData();
//        List<V1Beta1PipelineRun> listData = JSON.parseArray(string, V1Beta1PipelineRun.class);

        if (CollectionUtils.isEmpty(listData)) {
//            future.cancel(true);
            //redis记录丢失次数，超过一定次数取消，避免死线程
            String key = Constant.FAIL_PIPELINE_COUNT_KEY + pipelineInstanceCode;
            Integer count = Math.toIntExact(redisHelper.incrby(key, 0));
            if (count <= 15) {
                Long incrby = redisHelper.incrby(key, 1);
                return;
            }
            future.cancel(true);
        }
        V1Beta1PipelineRun pipelineRun = listData.get(0);

        String status = pipelineRun.getStatus().getConditions().get(0).getReason();
//        Map<String, V1Beta1PipelineRunTaskRunStatus> taskRuns = pipelineRun.getStatus().getTaskRuns();

        log.info("pipelinerun status is " + status);
        //Running Succeeded PipelineRunStopping pipelineRun的状态定义
        if (ContainerStatusEnum.Running.getKey().equals(status)) {
            log.info("track Running ");
            trackTaskService.trackRunningPipeline(pipelineRun, pipeline);
//            trackTasks(kubeConfig, pipelineInstanceCode, pipeline);
        } else if (ContainerStatusEnum.Succeeded.getKey().equals(status)) {
            log.info("track Succeeded ");
//            trackTasks(kubeConfig, pipelineInstanceCode, pipeline);
            trackTaskService.trackSuccessPipeline(pipelineRun, pipeline);
            //            成功状态, 查询所有pod，更新写入状态和out, resultTip等兜底.
            saveSuccessPipelineInstance(pipelineInstance, pipelineRun);
            future.cancel(true);
        } else if (ContainerStatusEnum.Cancelled.getKey().equals(status)) {
            log.info("track Cancelled ");
            future.cancel(true);
        } else {
//            非运行成功 结束轮询
            log.info("track other status ");
            trackTaskService.trackRunningPipeline(pipelineRun, pipeline);
            saveFailedPipelineInstance(pipelineInstance, pipelineRun);
//            trackTasks(kubeConfig, pipelineInstanceCode, pipeline);
            future.cancel(true);
        }

    }

    private void saveFailedPipelineInstance(PipelineInstance pipelineInstance, V1Beta1PipelineRun pipelineRun) {
        pipelineInstance.setPipelineStatus(PipelineInstanceEnum.failed.getKey());
        pipelineInstance.setEndTime(TektonUtil.getDate2offsetDate(pipelineRun.getStatus().getCompletionTime()));
        pipelineInstanceDomainService.update(pipelineInstance);
    }

    private void saveSuccessPipelineInstance(PipelineInstance pipelineInstance, V1Beta1PipelineRun pipelineRun) {
        pipelineInstance.setPipelineStatus(PipelineInstanceEnum.success.getKey());
        pipelineInstance.setEndTime(TektonUtil.getDate2offsetDate(pipelineRun.getStatus().getCompletionTime()));
        pipelineInstanceDomainService.update(pipelineInstance);
    }


    private void trackTasks(String kubeConfig, String pipelineInstanceCode, Pipeline pipeline) {
        String envId = pipeline.getEnvironmentUuid();
        String pipelineCode = pipeline.getCode();
        List<TaskInstance> taskInstances = taskInstanceDomainService.queryByPipelineInstanceCode(pipelineInstanceCode);
        for (TaskInstance taskInstance : taskInstances) {
            V1PodList v1PodList = getPodList(kubeConfig, taskInstance);
            if (null == v1PodList || 0 >= v1PodList.getItems().size()) {
                continue;
            }
//            log.info("tack pod info:"+ JSON.toJSONString(v1PodList.getItems()));
            V1Pod v1Pod = v1PodList.getItems().get(0);
            taskInstance.setAction(getTaskAction(taskInstance, envId));
            if (null != v1Pod.getStatus() && null != v1Pod.getStatus().getPhase()) {
                Integer taskStatus = getTaskStatus(v1Pod);
                taskInstance.setTaskStatus(taskStatus);
                // 任务失败时记录消息（同时判断配置是否开启）
                if (taskStatus.equals(TaskInstanceEnum.failed.getKey())) {
                    TriggerSetting triggerSetting = triggerSettingDomainService.queryByPipelineCode(pipelineCode);
                    if (Objects.nonNull(triggerSetting.getIsRunNotify()) && triggerSetting.getIsRunNotify().equals(YesOrNoEnum.YES.getValue())) {
                        List<String> toNotifyUserList = pipelineService.findPipelineNotifyReceiverList(pipelineCode);
                        UserMessageSaveDTO userMessageSaveDTO = new UserMessageSaveDTO();
                        userMessageSaveDTO.setMsgType(MsgConstant.MSG_TYPE_TEXT);
                        userMessageSaveDTO.setTitle(String.format("流水线 %s 的任务失败", pipeline.getName()));
                        userMessageSaveDTO.setContent(String.format("流水线编码为：%s；失败任务为： %s", pipelineCode, taskInstance.getName()));
                        userMessageSaveDTO.setReceiveUserIds(toNotifyUserList);
                        msgUserMessagesService.saveMessage(userMessageSaveDTO);
                    }
                }
            } else {
                if (Objects.nonNull(taskInstance.getStartTime())) {
                    taskInstance.setTaskStatus(TaskInstanceEnum.running.getKey());
                }
            }
            if (null != v1Pod.getStatus() && null != v1Pod.getStatus().getStartTime()) {
//            taskInstance.setResultTip(getTaskResultTip(v1Pod, pipeline, taskInstance.getTaskUuid()));
                taskInstance.setStartTime(TektonUtil.getDate2offsetDate(v1Pod.getStatus().getStartTime()));
                taskInstance.setEndTime(getEndTime(v1Pod));
            }
            taskInstance.setUpdateTime(new Date());
            specialMangeTask(taskInstance, v1Pod, pipeline);
            taskInstanceDomainService.update(taskInstance);
        }
    }

    private Date getEndTime(V1Pod v1Pod) {
        if (!v1Pod.getStatus().getPhase().equals(ContainerStatusEnum.Running.getKey())) {
            //非运行状态有结束时间
            OffsetDateTime finishedAt = null;
            if (v1Pod != null && v1Pod.getStatus() != null && v1Pod.getStatus().getContainerStatuses() != null && !v1Pod.getStatus().getContainerStatuses().isEmpty()) {
                //获取第一个容器的状态
                V1ContainerStatus containerStatus = v1Pod.getStatus().getContainerStatuses().get(v1Pod.getStatus().getContainerStatuses().size() - 1);
                if (containerStatus.getState() != null && containerStatus.getState().getTerminated() != null && containerStatus.getState().getTerminated().getFinishedAt() != null) {
                    finishedAt = containerStatus.getState().getTerminated().getFinishedAt();
                    return TektonUtil.getDate2offsetDate(finishedAt);
                }
            }
        }

        return null;
    }

    private TaskResultInfo getApproveTip(String taskInstanceCode) {
        List<Map<String, String>> data = new ArrayList<>();
        HashMap<String, String> noAccessMap = new HashMap<>();
        noAccessMap.put("buttonName", "验证不通过");
        noAccessMap.put("url", "/devops/pipelineInstance/approve/0/" + taskInstanceCode);
        noAccessMap.put("color", "red");
        data.add(noAccessMap);

        HashMap<String, String> accessMap = new HashMap<>();
        accessMap.put("buttonName", "验证通过");
        accessMap.put("url", "/devops/pipelineInstance/approve/1/" + taskInstanceCode);
        accessMap.put("color", "blue");
        data.add(accessMap);
        return TaskResultInfo.builder().type(TaskResultTypeEnum.invoke.getKey()).data(data).position("center").build();

    }

    private TaskResultInfo getTaskScanTip(String uniqueCode) {
        List<Map<String, String>> data = new ArrayList<>();
        MeasDTO measDTO = sonarqubeService.getSonarScanResult(uniqueCode);
        measDTO.getComponent().getMeasures().forEach(meas -> {
            HashMap<String, String> tipMap = new HashMap<>();
            tipMap.put("value", meas.getValue());
            tipMap.put("label", RedLineInfoEnum.fromKey(meas.getMetric()).getValue());
            tipMap.put("color", "red");
            data.add(tipMap);
        });
        return TaskResultInfo.builder().type(TaskResultTypeEnum.bottomInfo.getKey()).data(data).position("center").build();
    }

    private TaskResultInfo getTaskErrorTip(V1Pod v1Pod) {
        List<V1ContainerStatus> containerStatuses = v1Pod.getStatus().getContainerStatuses();
        if (CollectionUtils.isEmpty(containerStatuses)) {
            return null;
        }
        String errorMessage = getErrorMessage(v1Pod);
        List<Map<String, String>> data = new ArrayList<>();
        HashMap<String, String> tipMap = new HashMap<>();
        tipMap.put("tip", errorMessage);
        data.add(tipMap);
        return TaskResultInfo.builder().type(TaskResultTypeEnum.errorTip.getKey()).data(data).position("center").build();
    }

    private TaskResultInfo getTaskTip(String tip) {
        List<Map<String, String>> data = new ArrayList<>();
        HashMap<String, String> tipMap = new HashMap<>();
        tipMap.put("tip", tip);
        data.add(tipMap);
        return TaskResultInfo.builder().type(TaskResultTypeEnum.errorTip.getKey()).data(data).position("center").build();
    }

    @Nullable
    private String getErrorMessage(V1Pod v1Pod) {
        String errorMessage = "";
        if (v1Pod != null && v1Pod.getStatus() != null && v1Pod.getStatus().getContainerStatuses() != null && !v1Pod.getStatus().getContainerStatuses().isEmpty()) {
            //获取第一个容器的状态
            V1ContainerStatus containerStatus = v1Pod.getStatus().getContainerStatuses().get(0);
            if (containerStatus.getState() != null && containerStatus.getState().getTerminated() != null && containerStatus.getState().getTerminated().getReason() != null) {
                errorMessage = v1Pod.getStatus().getContainerStatuses().get(0).getState().getTerminated().getReason();
            }
        }
        return errorMessage;
    }

    private Integer getTaskStatus(V1Pod v1Pod) {
        Integer status;
        if (v1Pod.getStatus().getPhase().equals(ContainerStatusEnum.Succeeded.getKey())) {
            status = TaskInstanceEnum.success.getKey();
        } else if (v1Pod.getStatus().getPhase().equals(ContainerStatusEnum.Running.getKey())) {
            status = TaskInstanceEnum.running.getKey();
        } else if (v1Pod.getStatus().getPhase().equals(ContainerStatusEnum.NotReady.getKey())) {
            status = TaskInstanceEnum.running.getKey();
        } else if (v1Pod.getStatus().getPhase().equals(ContainerStatusEnum.Pending.getKey())) {
            status = TaskInstanceEnum.running.getKey();
        } else {
            status = TaskInstanceEnum.failed.getKey();
        }
        return status;
    }

    private V1PodList getPodList(String kubeConfig, TaskInstance taskInstance) {
        String taskPodName = taskInstance.getCode();
//        PodListRequest podListRequest = PodListRequest.builder()
//                .kubeConfig(kubeConfig)
//                .namespaceName(Constant.BUILD_NAMESPACE)
//                .podName(taskPodName)
//                .build();
        QueryDTO podListRequest = new QueryDTO();
        podListRequest.setKubeConfig(kubeConfig);
        podListRequest.setNamespaceName(Constant.BUILD_NAMESPACE);
        podListRequest.setPodName(taskPodName);
        ApiResult<V1PodList> v1PodListApiResult = podService.getPodList(podListRequest);
        return v1PodListApiResult.getData();
    }

    private String getTaskAction(TaskInstance taskInstance, String envId) {
        List<TaskOutput> actionList = JSON.parseArray(taskInstance.getAction(), TaskOutput.class);
        if (CollectionUtils.isEmpty(actionList)) {
            //为空首次才加入日志按钮，后续不处理。
            actionList = new ArrayList<>();
            TaskOutput taskOutput = getLogAction(taskInstance, envId);
            actionList.add(taskOutput);
        }
        //actionList不含logAction才加入
        return JSON.toJSONString(actionList);
    }

    @NotNull
    private TaskOutput getLogAction(TaskInstance taskInstance, String envId) {
        TaskOutput taskOutput = new TaskOutput();
        taskOutput.setActionType(ActionTypeEnum.logButton.getKey());
        taskOutput.setActionUrl("/taskLog-stream?podName=" + taskInstance.getCode() + "&envId=" + envId + "&containerName=step-main");
        taskOutput.setActionName("查看日志");
        taskOutput.setIcon("log-icon");
        return taskOutput;
    }

    private void specialMangeTask(TaskInstance taskInstance, V1Pod v1Pod, Pipeline pipeline) {
        //先统一处理， 后续设计可以补充Def的output，根据output规则动态处理  String taskInstanceOutput = "[\"logAction\",\"invoke\"]";
        String code = taskInstance.getCode();
        Integer taskStatus = taskInstance.getTaskStatus();
        //第一先存入了一个日志按钮
        List<TaskOutput> actionList = JSON.parseArray(taskInstance.getAction(), TaskOutput.class);
        //resultnfo先不设置，特殊处理新建
        List<TaskResultInfo> resultInfoList = new ArrayList<>();
        //todo 这一块腐了， 任务实例根据状态抽离
        //失败处理
        if (TaskInstanceEnum.failed.getKey().equals(taskStatus)) {
            if (v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.sonarqube.getKey()) && StringUtils.isEmpty(taskInstance.getResultTip())) {
                HashMap<String, String> paramTaskMap = TektonUtil.parseTaskParamMap2O(taskInstance.getParams());
                if (paramTaskMap.containsKey(DeployTaskFieldEnum.alertInfo.name())) {
                    String alertInfo = paramTaskMap.get(DeployTaskFieldEnum.alertInfo.name());
                    List<AlertInfo> alertInfoList = JSON.parseArray(alertInfo, AlertInfo.class);
                    TaskResultInfo alertHead = getTaskTip("扫描结果触发红线");
                    resultInfoList.add(alertHead);
                    StringBuffer sb = new StringBuffer();
                    for (int i = 0; i < alertInfoList.size(); i++) {
                        AlertInfo ai = alertInfoList.get(i);
                        sb.append(RedLineInfoEnum.fromKey(ai.identifier).getValue())
                                .append("\t")
                                .append(ExpressionTypeEum.fromValue(ai.type).getKey())
                                .append("\t")
                                .append(ai.threshold);

                        if (i < alertInfoList.size() - 1) {
                            sb.append("\t且\t");
                        }
                    }
                    TaskResultInfo alertTipInfo = getTaskTip(sb.toString());
                    resultInfoList.add(alertTipInfo);
                    //显示扫描结果
                    String environmentUuid = pipeline.getEnvironmentUuid();
                    Environment environment = environmentDomainService.query(environmentUuid);
                    String uniqueCode = pipeline.getComponentLabel() + "-" + environment.getCode();
                    TaskResultInfo resultInfo = getTaskScanTip(uniqueCode);
                    resultInfoList.add(resultInfo);
                    //显示查看详情接口
                    TaskOutput action = getSonarDetailAction(uniqueCode);
                    actionList.add(action);
                }
            }
            //失败提示
            TaskResultInfo resultTip = getTaskErrorTip(v1Pod);
            if (!Objects.isNull(resultTip) && !v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.sonarqube.getKey())
                    && !v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.approve.getKey())) {
                resultInfoList.add(resultTip);
            }
        }

        //成功处理
        if (TaskInstanceEnum.success.getKey().equals(taskStatus)) {
            //成功状态 ，且没有写过数据的任务 代码扫描的显示
            if (v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.sonarqube.getKey()) && StringUtils.isEmpty(taskInstance.getResultTip())) {
                //显示扫描结果
                String environmentUuid = pipeline.getEnvironmentUuid();
                Environment environment = environmentDomainService.query(environmentUuid);
                String uniqueCode = pipeline.getComponentLabel() + "-" + environment.getCode();
                TaskResultInfo resultInfo = getTaskScanTip(uniqueCode);
                resultInfoList.add(resultInfo);
                //显示查看详情接口
                TaskOutput action = getSonarDetailAction(uniqueCode);
                actionList.add(action);
            }

        }

        //运行中处理
        //人工卡点
        if (v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.approve.getKey())) {
            if (StringUtils.isEmpty(taskInstance.getResultTip())) {
                TaskResultInfo resultInfo = getApproveTip(taskInstance.getCode());
                resultInfoList.add(resultInfo);
            }
        }
        //部署单处理
        if (v1Pod.getMetadata().getName().contains(TaskDefCodeEnum.deploy.getKey())) {
            deploymentUnitProcess(taskInstance, pipeline);
        }

        taskInstance.setAction(JSON.toJSONString(actionList));
        if (CollectionUtils.isNotEmpty(resultInfoList)) {
            taskInstance.setResultTip(JSON.toJSONString(resultInfoList));
        }

    }

    private void deploymentUnitProcess(TaskInstance taskInstance, Pipeline pipeline) {
        DeploymentUnitQuery query = DeploymentUnitQuery.builder().pipelineInstanceCode(taskInstance.getPipelineInstanceCode()).build();
        PageRecord<DeploymentUnit> record = deploymentUnitDomainService.pageByCondition(1, 1, query);
        List<DeploymentUnit> records = record.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            //这里需要处理，只能插入一次
            DeploymentUnit deploymentUnit = new DeploymentUnit();
            deploymentUnit.setComponentLabel(pipeline.getComponentLabel());
            deploymentUnit.setEnvironmentUuid(pipeline.getEnvironmentUuid());
            deploymentUnit.setPipelineInstanceCode(taskInstance.getPipelineInstanceCode());
            deploymentUnit.setCreateTime(taskInstance.getCreateTime());
            deploymentUnit.setCreatorId(taskInstance.getCreatorId());
            //唯一标识
            deploymentUnit.setTaskInstanceCode(taskInstance.getCode());
            String redisKey = Constant.DEPLOYMENT_VERSION_KEY + pipeline.getComponentLabel() + "." + pipeline.getEnvironmentUuid();
            deploymentUnit.setDeploymentVersion(redisHelper.incrby(redisKey, 1).toString());
            deploymentUnit.setDeploymentName(Constant.DEPLOYMENT_UNIT_NAME + "-" + deploymentUnit.getDeploymentVersion());
            deploymentUnit.setProgramVersion(pipeline.getCode());
            HashMap<String, String> hashMap = JSONObject.parseObject(taskInstance.getParams(), HashMap.class);
            deploymentUnit.setTargetReplicas(new BigDecimal(String.valueOf(hashMap.get(DeployTaskFieldEnum.replicas.getKey()))).intValueExact());
            deploymentUnit.setDeploymentWay(Integer.valueOf(hashMap.get(DeployTaskFieldEnum.deployStrategy.getKey())));
            deploymentUnit.setBatchCount(hashMap.containsKey(DeployTaskFieldEnum.batchesNum.getKey()) ? new BigDecimal(String.valueOf(hashMap.get(DeployTaskFieldEnum.batchesNum.getKey()))).intValueExact() : null);
            deploymentUnit.setDeploymentProgress(hashMap.containsKey(DeployTaskFieldEnum.batchesNum.getKey()) ? DeployUnitEnum.First.getKey() : null);
            deploymentUnitDomainService.add(deploymentUnit);
        }
    }

    private TaskOutput getSonarDetailAction(String uniqueCode) {
        String server = getSonarServer();
        TaskOutput taskOutput = new TaskOutput();
        taskOutput.setActionType(ActionTypeEnum.redirect.getKey());
        taskOutput.setActionUrl(server + "/project/issues?id=" + uniqueCode);
        taskOutput.setActionName("查看详情");
        taskOutput.setIcon("log-icon");
        return taskOutput;
    }

    private String getSonarServer() {
        ToolChainQuery query = new ToolChainQuery();
        query.setType(ToolChainTypeEnum.TYPE_QA.getTypeKey());
        PageRecord<ToolChain> toolChainPageRecord = toolChainDomainService.pageList(1, 1, query);
        String server = toolChainPageRecord.getRecords().get(0).getServer();
        return server;
    }

    private String getClusterKubeConfig(Pipeline pipeline) {
//        String kubeconfig = (String)redisHelper.get(Constant.);
//        if (StringUtils.isNotEmpty(kubeconfig)) {
//            return kubeconfig;
//        }
//       else{
        Environment environment = environmentDomainService.query(pipeline.getEnvironmentUuid());
        Space space = spaceDomainService.query(environment.getSpaceUuid());
        Cluster cluster = clusterDomainService.query(space.getClusterUuid());
        String kubeconfig = cluster.getKubeConfig();
//            redisHelper.set(,kubeconfig);

//        }
        return kubeconfig;

    }

    @Override
    public void afterPropertiesSet() throws Exception {
        scheduledExecutorService = Executors.newScheduledThreadPool(10);
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TaskOutput {
        /**
         * 类型logButton,redirect,invoke
         */
        private String actionType;
        /**
         * 名字
         */
        private String actionName;
        /**
         * 调用url
         */
        private String actionUrl;
        /**
         * 唯一标识
         */
        private String actionId;
        /**
         * 展示顺序
         */
        private Integer index;
        /**
         * 展示 icon
         */
        private String icon;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class TaskResultInfo {
        /**
         * 类型 errorTip，bottomInfo，invoke，checkPoint
         */
        private String type;
        /**
         * 数据
         */
        private List<Map<String, String>> data;
        /**
         * 显示位置   left,center
         */
        private String position;
    }

    @Data
    public static class AlertInfo {
        String identifier;
        String threshold;
        String type;
    }
}
